home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / ae_14.zip / AE2.PAS < prev    next >
Pascal/Delphi Source File  |  1991-02-27  |  17KB  |  462 lines

  1. unit AE2 ;
  2.  
  3. {$B-}
  4. {$I-}
  5. {$S+}
  6. {$V-}
  7.  
  8. {-----------------------------------------------------------------------------}
  9. { This unit contains all movement procedures.                                 }
  10. { All procedures operate on the current workspace (indicated by CurrentWsnr), }
  11. { unless specified otherwise.                                                 }
  12. {-----------------------------------------------------------------------------}
  13.  
  14. interface
  15.  
  16. uses Crt,Dos,AE0,AE1 ;
  17.  
  18. procedure Home (var P:Position) ;
  19. procedure EndOfLine (var P:Position) ;
  20. procedure CalculateColnr (var P:position) ;
  21. procedure SkipDown (var P:Position ; Distance:word) ;
  22. procedure SkipUp (var P:Position ; Distance:word) ;
  23. procedure WordDown (var P:Position) ;
  24. procedure WordUp (var P:Position) ;
  25. procedure LineDown (var P:Position) ;
  26. procedure LineUp (var P:Position) ;
  27. procedure SearchUp (Target:string ; var P:Position ; LimitIndex:word) ;
  28. procedure SearchDown (Target:string ; var P:Position ; LimitIndex:word) ;
  29. procedure SearchString (Target:string ; var P:Position) ;
  30. procedure MatchBracketsDown (OpenBracket,CloseBracket:char ; var P:Position) ;
  31. procedure MatchBracketsUp (OpenBracket,CloseBracket:char ; var P:Position) ;
  32.  
  33. implementation
  34.  
  35. {-----------------------------------------------------------------------------}
  36. { Sets P to the first column of the line it is pointing to                    }
  37. {-----------------------------------------------------------------------------}
  38.  
  39. procedure Home (var P:Position) ;
  40.  
  41. begin
  42. Dec (P.Index,P.Colnr-1) ;
  43. P.Colnr := 1 ;
  44. end ;
  45.  
  46. {-----------------------------------------------------------------------------}
  47. { Sets P to the last column of the line it is pointing to (CR or end of file) }
  48. {-----------------------------------------------------------------------------}
  49.  
  50. procedure EndOfLine (var P:Position) ;
  51.  
  52. begin
  53. with Workspace[CurrentWsnr] do
  54.      begin
  55.      while (Buffer^[P.Index] <> CR) and
  56.            (P.Index < Buffersize) do
  57.            begin
  58.            Inc (P.Index) ;
  59.            Inc (P.Colnr) ;
  60.            end ;
  61.      end ; { of with }
  62. end ;
  63.  
  64. {-----------------------------------------------------------------------------}
  65. { Re-calculates the column number by searching for a previous line feed       }
  66. {-----------------------------------------------------------------------------}
  67.  
  68. procedure CalculateColnr (var P:position) ;
  69.  
  70. begin
  71. with Workspace[CurrentWsnr] do
  72.      begin
  73.      if P.Linenr = 1
  74.         then P.Colnr := P.Index
  75.         else begin
  76.              P.Colnr := 1 ;
  77.              while (Buffer^[P.Index-P.Colnr] <> CR) do Inc (P.Colnr) ;
  78.              if Buffer^[P.Index-P.Colnr+1] = LF
  79.                 then Dec (P.Colnr) ;
  80.              end ;
  81.      end ;
  82. end ;
  83.  
  84. {-----------------------------------------------------------------------------}
  85. { Skips P <Distance> positions downward, adjusting line and column number.    }
  86. { If the end of the buffer is reached, the procedure stops.                   }
  87. {-----------------------------------------------------------------------------}
  88.  
  89. procedure SkipDown (var P:Position ; Distance:word) ;
  90.  
  91. var Counter : word ;
  92.  
  93. begin
  94. with Workspace[CurrentWsnr] do
  95.      begin
  96.      for Counter := 1 to Distance do
  97.          begin
  98.          if P.Index = BufferSize then Exit ;
  99.          if Buffer^[P.Index] = CR
  100.             then begin
  101.                  Inc (P.Linenr) ;
  102.                  if Buffer^[P.Index+1] = LF
  103.                     then P.Colnr := 0
  104.                     else P.Colnr := 1 ;
  105.                  end
  106.             else Inc (P.Colnr) ;
  107.          Inc (P.Index) ;
  108.          end ;
  109.      end ;
  110. end ;
  111.  
  112. {-----------------------------------------------------------------------------}
  113. { Skips P <Distance> positions upward, adjusting line and column number.      }
  114. { If the start of the buffer is reached, the procedure stops.                 }
  115. {-----------------------------------------------------------------------------}
  116.  
  117. procedure SkipUp (var P:Position ; Distance:word) ;
  118.  
  119. var Counter : word ;
  120.  
  121. begin
  122. with Workspace[CurrentWsnr] do
  123.      begin
  124.      if Distance < P.Colnr
  125.         then begin
  126.              { P will remain within current line }
  127.              Dec (P.Colnr,Distance) ;
  128.              Dec (P.Index,Distance) ;
  129.              end
  130.         else begin
  131.              if P.Index <= Distance
  132.                 then begin
  133.                      { go to start of buffer }
  134.                      P.Index := 1 ;
  135.                      P.Colnr := 1 ;
  136.                      Exit ;
  137.                      end ;
  138.              for Counter := 1 to Distance do
  139.                  begin
  140.                  Dec (P.Index) ;
  141.                  if Buffer^[P.Index] = CR
  142.                     then Dec (P.Linenr) ;
  143.                  end ;
  144.              CalculateColnr (P) ;
  145.              end ;
  146.      end ;
  147. end ;
  148.  
  149. {-----------------------------------------------------------------------------}
  150. { Skips P downward until the beginning of the next word in the text.          }
  151. {-----------------------------------------------------------------------------}
  152.  
  153. procedure WordDown (var P:Position) ;
  154.  
  155. begin
  156. with Workspace[CurrentWsnr] do
  157.      begin
  158.      while not ((Buffer^[P.Index] in WordSeparators) or
  159.                 (P.Index = BufferSize)) do
  160.            begin
  161.            Inc (P.Colnr) ;
  162.            Inc (P.Index) ;
  163.            end ;
  164.      while (Buffer^[P.Index] in WordSeparators) and
  165.            (P.Index < BufferSize) do
  166.            begin
  167.            if Buffer^[P.Index] = CR
  168.               then begin
  169.                    Inc (P.Linenr) ;
  170.                    if Buffer^[P.Index+1] = LF
  171.                     then P.Colnr := 0
  172.                     else P.Colnr := 1 ;
  173.                    end
  174.               else Inc (P.Colnr) ;
  175.            Inc (P.Index) ;
  176.            end ;
  177.      end ;
  178. end ;
  179.  
  180. {-----------------------------------------------------------------------------}
  181. { Skips P upward until the beginning of the previous word in the text.        }
  182. {-----------------------------------------------------------------------------}
  183.  
  184. procedure WordUp (var P:Position) ;
  185.  
  186. begin
  187. with Workspace[CurrentWsnr] do
  188.      begin
  189.      if P.Index > 1
  190.         then begin
  191.              repeat Dec (P.Index) ;
  192.                     if Buffer^[P.Index] = CR
  193.                        then Dec (P.Linenr) ;
  194.              until ((not (Buffer^[P.Index] in WordSeparators)) or
  195.                     (P.Index = 1)) ;
  196.              while ((not (Buffer^[P.Index] in WordSeparators)) and
  197.                     (P.Index > 0)) do
  198.                    begin
  199.                    Dec (P.Index) ;
  200.                    end ;
  201.              Inc (P.Index) ;
  202.              CalculateColnr (P) ;
  203.              end ;
  204.      end ;
  205. end ;
  206.  
  207. {-----------------------------------------------------------------------------}
  208. { Skips P downward to the first column of the next line.                      }
  209. { If the end of the buffer is reached, the procedure stops.                   }
  210. {-----------------------------------------------------------------------------}
  211.  
  212. procedure LineDown (var P:Position) ;
  213.  
  214. var StartIndex : word ;
  215.  
  216. begin
  217. StartIndex := P.Index ;
  218. with Workspace[CurrentWsnr] do
  219.      begin
  220.      while (Buffer^[P.Index] <> CR) and (P.Index < BufferSize) do
  221.            Inc (P.Index) ;
  222.      if (Buffer^[P.Index] = CR)
  223.         then begin
  224.              Inc (P.Index) ;
  225.              if Buffer^[P.Index] = LF
  226.                 then Inc (P.Index) ;
  227.              P.Colnr := 1 ;
  228.              Inc (P.Linenr) ;
  229.              end
  230.         else Inc (P.Colnr,P.Index-StartIndex) ;
  231.      end ;
  232. end ;
  233.  
  234. {-----------------------------------------------------------------------------}
  235. { Skips P upward to the first column of the previous line.                    }
  236. { If the start of the buffer is reached, the procedure stops.                 }
  237. {-----------------------------------------------------------------------------}
  238.  
  239. procedure LineUp (var P:Position) ;
  240.  
  241. begin
  242. if P.Linenr = 1
  243.    then Dec (P.Index,P.Colnr-1)
  244.    else with workspace[CurrentWsnr] do
  245.              begin
  246.              { go past carriage return at start of current line }
  247.              Dec (P.Index,P.Colnr+1) ;
  248.              if Buffer^[P.Index+1] = LF then Dec (P.Index) ;
  249.              { find start of line }
  250.              while (Buffer^[P.Index] <> CR) and (P.Index > 0) do
  251.                    Dec (P.Index) ;
  252.              if Buffer^[P.Index+1] = LF
  253.                 then Inc (P.Index,2)
  254.                 else Inc (P.Index) ;
  255.              Dec (P.Linenr) ;
  256.              end ;
  257. P.Colnr := 1 ;
  258. end ;
  259.  
  260. {-----------------------------------------------------------------------------}
  261. { Searches downward for the string <Target>. On exit, P points to the first   }
  262. { character of the string in the text buffer, if the string is found before   }
  263. { index <LimitIndex> is reached. Otherwise, P will point to <LimitIndex>.     }
  264. { The value of global variable Found will be set accordingly.                 }
  265. {-----------------------------------------------------------------------------}
  266.  
  267. procedure SearchDown (Target:string ; var P:Position ; LimitIndex:word) ;
  268.  
  269. var Counter : byte ;
  270.  
  271. begin
  272. Found := False ;
  273. with Workspace[Currentwsnr] do
  274.      begin
  275.      if IgnoreCase
  276.         then begin
  277.              { case-insensitive search }
  278.              Target := UpperCase (Target) ;
  279.              while (not Found) and (P.Index <= LimitIndex) do
  280.                    begin
  281.                    { search text for first character of Target }
  282.                    repeat if Buffer^[P.Index] = CR
  283.                              then Inc (P.Linenr) ;
  284.                           Inc (P.Index) ;
  285.                    until (UpCase(Buffer^[P.Index]) = Target[1]) or
  286.                          (P.Index > LimitIndex) ;
  287.                    Counter := 2 ;
  288.                    { check if following characters are equal to Target }
  289.                    while (UpCase(Buffer^[P.Index+Counter-1]) = Target[Counter])
  290.                          and (Counter <= Length(Target)) do
  291.                          Inc (Counter) ;
  292.                    Found := (Counter > Length(Target)) and
  293.                             ((P.Index + Length(Target) - 1) <= LimitIndex)
  294.                    end ; { of while }
  295.              end { of case-insensitive search }
  296.         else begin
  297.              { normal search }
  298.              while (not Found) and (P.Index <= LimitIndex) do
  299.                    begin
  300.                    { search text for first character of Target }
  301.                    repeat if Buffer^[P.Index] = CR
  302.                              then Inc (P.Linenr) ;
  303.                           Inc (P.Index) ;
  304.                    until (Buffer^[P.Index] = Target[1]) or
  305.                          (P.Index > LimitIndex) ;
  306.                    Counter := 2 ;
  307.                    { check if following characters are equal to Target }
  308.                    while (Buffer^[P.Index+Counter-1] = Target[Counter]) and
  309.                          (Counter <= Length(Target)) do
  310.                          Inc (Counter) ;
  311.                    Found := (Counter > Length(Target)) and
  312.                             ((P.Index + Length(Target) - 1) <= LimitIndex)
  313.                    end ; { of while }
  314.              end ; { of normal search }
  315.      CalculateColnr (P) ;
  316.      end ; { of with }
  317. end ; { of procedure }
  318.  
  319. {-----------------------------------------------------------------------------}
  320. { Searches upward for the string <Target>. On exit, P points to the first     }
  321. { character of the string in the text buffer, if the string is found before   }
  322. { index <LimitIndex> is reached. Otherwise, P will point to <LimitIndex>.     }
  323. { The value of global variable Found will be set accordingly.                 }
  324. {-----------------------------------------------------------------------------}
  325.  
  326. procedure SearchUp (Target:string ; var P:Position ; LimitIndex:word) ;
  327.  
  328. var Counter : word ;
  329.  
  330. begin
  331. Found := False ;
  332. with Workspace[CurrentWsnr] do
  333.      begin
  334.      if IgnoreCase
  335.         then begin
  336.              { case-insensitive search }
  337.              Target := UpperCase (Target) ;
  338.              while (not Found) and (P.Index >= LimitIndex) do
  339.                    begin
  340.                    { search text for first character of Target }
  341.                    repeat Dec (P.Index) ;
  342.                           if Buffer^[P.Index] = CR
  343.                              then Dec (P.Linenr) ;
  344.                    until (UpCase(Buffer^[P.Index]) = Target[1]) or
  345.                          (P.Index < LimitIndex) ;
  346.                    Counter := 2 ;
  347.                    { check if following characters are equal to Target }
  348.                    while (UpCase(Buffer^[P.Index+Counter-1]) =
  349.                           Target[Counter]) and
  350.                          (Counter <= Length(Target)) do
  351.                          Inc (Counter) ;
  352.                    Found := (Counter > Length(Target)) and
  353.                             (P.Index >= LimitIndex) ;
  354.                    end ; { of while }
  355.              end { of case-insensitive search }
  356.         else begin
  357.              { normal search }
  358.              while (not Found) and (P.Index >= LimitIndex) do
  359.                    begin
  360.                    { search text for first character of Target }
  361.                    repeat Dec (P.Index) ;
  362.                           if Buffer^[P.Index] = CR
  363.                              then Dec (P.Linenr) ;
  364.                    until (Buffer^[P.Index] = Target[1]) or
  365.                          (P.Index < LimitIndex) ;
  366.                    Counter := 2 ;
  367.                    { check if following characters are equal to Target }
  368.                    while (Buffer^[P.Index+Counter-1] = Target[Counter]) and
  369.                          (Counter <= Length(Target)) do
  370.                          Inc (Counter) ;
  371.                    Found := (Counter > Length(Target)) and
  372.                             (P.Index >= LimitIndex) ;
  373.                    end ; { of while }
  374.              end { of normal search } ;
  375.      CalculateColnr (P) ;
  376.      end ; { of with }
  377. end ; { of procedure }
  378.  
  379. {-----------------------------------------------------------------------------}
  380. { Performs a general search for <Target> according to the search options      }
  381. { that are stored in global boolean variables. (Searching is done by calling  }
  382. { SearchDown or SearchUp.) If Target is found, P will point to the first      }
  383. { character.                                                                  }
  384. {-----------------------------------------------------------------------------}
  385.  
  386. procedure SearchString (Target:string ; var P:Position) ;
  387.  
  388. begin
  389. if Length(Target) = 0
  390.    then Found := False
  391.    else begin
  392.         with Workspace[CurrentWsnr] do
  393.              begin
  394.              if ReverseSearch
  395.                 then SearchUp (Target,P,1)
  396.                 else SearchDown (Target,P,BufferSize-1) ;
  397.              end ; { of with }
  398.         end ;
  399. end ;
  400.  
  401. {-----------------------------------------------------------------------------}
  402. { Searches downward for an occurrence of CloseBracket in the buffer,          }
  403. { matching the OpenBracket that P is assumed to point at when the procedure   }
  404. { is called. If no matching bracket is found, P will point to the end of the  }
  405. { buffer, and Found is set to False.                                          }
  406. {-----------------------------------------------------------------------------}
  407.  
  408. procedure MatchBracketsDown (OpenBracket,CloseBracket:char ; var P:Position) ;
  409.  
  410. var Level : integer ;
  411.     { Level keeps track of the nesting level of the brackets }
  412.  
  413. begin
  414. Level := 1 ;
  415. with Workspace[CurrentWsnr] do
  416.      begin
  417.      while (Level > 0) and (P.Index < BufferSize) do
  418.            begin
  419.            if Buffer^[P.Index] = CR
  420.               then Inc (P.Linenr) ;
  421.            Inc (P.Index) ;
  422.            if Buffer^[P.Index] = OpenBracket then Inc (Level) ;
  423.            if Buffer^[P.Index] = CloseBracket then Dec (Level) ;
  424.            end ; { of while }
  425.      CalculateColnr (P) ;
  426.      end ;
  427. Found := (Level = 0) ;
  428. end ;
  429.  
  430. {-----------------------------------------------------------------------------}
  431. { Searches upward for an occurrence of CloseBracket in the buffer, matching   }
  432. { the OpenBracket that P is assumed to point at when the procedure is called. }
  433. { If no matching bracket is found, P will point to the start of the           }
  434. { buffer, and Found is set to False.                                          }
  435. {-----------------------------------------------------------------------------}
  436.  
  437. procedure MatchBracketsUp (OpenBracket,CloseBracket:char ; var P:Position) ;
  438.  
  439. var Level : integer ;
  440.     { Level keeps track of the nesting level of the brackets }
  441.  
  442. begin
  443. Level := -1 ;
  444. with Workspace[CurrentWsnr] do
  445.      begin
  446.      while (Level < 0) and (P.Index > 1) do
  447.            begin
  448.            Dec (P.Index) ;
  449.            if Buffer^[P.Index] = CR
  450.               then Dec (P.Linenr) ;
  451.            if Buffer^[P.Index] = OpenBracket then Inc (Level) ;
  452.            if Buffer^[P.Index] = CloseBracket then Dec (Level) ;
  453.            end ; { of while }
  454.      CalculateColnr (P) ;
  455.      end ;
  456. Found := (Level = 0) ;
  457. end ;
  458.  
  459. {-----------------------------------------------------------------------------}
  460.  
  461. end.
  462.